package cn.uai.activiti8.approval.service.impl;

import cn.uai.activiti8.approval.bus.AbstractBusinessBus;
import cn.uai.activiti8.approval.cmd.QueryHistoryUserTaskCmd;
import cn.uai.activiti8.approval.exception.OperationNotSupportedException;
import cn.uai.activiti8.approval.service.CommandExecutionService;
import cn.uai.activiti8.approval.service.InfrastructureService;
import cn.uai.activiti8.dto.Result;
import cn.uai.activiti8.entity.User;
import cn.uai.activiti8.service.UserService;
import com.alibaba.fastjson2.JSONObject;
import jakarta.annotation.Resource;
import org.activiti.engine.ActivitiTaskAlreadyClaimedException;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static cn.uai.activiti8.enums.RespCodeEnum.TASK_HAS_BEEN_SIGNED;
import static cn.uai.activiti8.enums.RespCodeEnum.TASK_TRANSFER_EXCEPTION;

/**
 * @desc 基础设施服务
 * @author uai
 * @since 2025/8/7 11:14
 * @version 1.0
 */
@Service
public class InfrastructureServiceImpl extends AbstractBusinessBus implements InfrastructureService {

    private static final Logger LOGGER = LoggerFactory.getLogger(InfrastructureServiceImpl.class);

    @Resource
    protected RuntimeService runtimeService;

    @Resource
    protected UserService userService;

    @Resource
    protected TaskService taskService;

    @Resource
    private CommandExecutionService commandExecutionService;

    @Override
    public ProcessInstance start(String processDefinitionId, Map<String, Object> variables) {
        return runtimeService.startProcessInstanceById(processDefinitionId, variables);
    }

    @Override
    public ProcessInstance startByKey(String processDefinitionKey, Map<String, Object> variables) {
        return runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
    }

    @Override
    public ProcessInstance startByKey(String processDefinitionKey, String businessKey, Map<String, Object> variables) {
        return runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
    }

    @Override
    public String taskQuery(Long uid) {
        String assignUid = String.valueOf(uid);
        List<Map<String, Object>> taskList = new ArrayList<>();
        List<Task> tasks = taskService.createTaskQuery().taskAssignee(assignUid).list();
        if (CollectionUtils.isEmpty(tasks)) {
            return Result.success(taskList);
        }
        tasks.forEach(task -> {
            Map<String, Object> taskMap = Map.of(
                    "taskId", task.getId(),
                    "taskName", task.getName(),
                    "processInstanceId", task.getProcessInstanceId());
            taskList.add(taskMap);
        });
        return Result.success(taskList);
    }

    @Override
    public String taskQuery(String userName) {
//      User user = userMapper.selectOneByQuery(QueryWrapper.create().eq("username", userName));
        User user = userService.userName2uid(userName);
        return taskQuery(user.getUid());
    }

    @Override
    public String candidateUserTaskQuery(String userName) {
        User uid = userService.userName2uid(userName);
        List<Map<String, Object>> taskList = new ArrayList<>();
        List<Task> tasks = taskService.createTaskQuery().taskCandidateUser(uid.getUid().toString()).list();
        if (CollectionUtils.isEmpty(tasks)) {
            return Result.success(taskList);
        }
        tasks.forEach(task -> {
            Map<String, Object> taskMap = Map.of(
                    "taskId", task.getId(),
                    "taskName", task.getName(),
                    "processInstanceId", task.getProcessInstanceId());
            taskList.add(taskMap);
        });
        return Result.success(taskList);
    }

    @Override
    public String candidateGroupTaskQuery(String groupName) {
        return null;
    }

    @Override
    public String claim(String body) {
        JSONObject bodyJson = JSONObject.parseObject(body);
        String userName = bodyJson.getString("userName");
        String taskId = bodyJson.getString("taskId");
        User user = userService.userName2uid(userName);
        String uid = String.valueOf(user.getUid());
        try {
            taskService.claim(taskId, uid);
        } catch (ActivitiTaskAlreadyClaimedException e) {
            LOGGER.error("任务 [ {} ] 已经被其他用户签收签收", taskId, e);
            return Result.exception(TASK_HAS_BEEN_SIGNED);
        }
        return Result.success();
    }

    @Override
    public String assign(String body) {
        JSONObject bodyJson = JSONObject.parseObject(body);
        String userName = bodyJson.getString("userName");
        String taskId = bodyJson.getString("taskId");
        User user = userService.userName2uid(userName);
        String uid = String.valueOf(user.getUid());
        try {
            taskService.setAssignee(taskId, uid);
        } catch (Exception e) {
            LOGGER.error("任务 [ {} ] 转办异常.", taskId, e);
            return Result.exception(TASK_TRANSFER_EXCEPTION);
        }
        return Result.success();
    }

    /**
     * 激活审批流程
     * @param body
     * @return
     */
    @Override
    public String activate(String body) {
        JSONObject jsonBody = JSONObject.parseObject(body);
        String processInstanceId = jsonBody.getString("processInstanceId");
        runtimeService.activateProcessInstanceById(processInstanceId);
        return Result.success();
    }

    /**
     * 挂起审批流程
     * @param body
     * @return
     */
    @Override
    public String suspend(String body) {
        JSONObject jsonBody = JSONObject.parseObject(body);
        String processInstanceId = jsonBody.getString("processInstanceId");
        runtimeService.suspendProcessInstanceById(processInstanceId);
        return Result.success();
    }

    @Override
    protected void dynamicAssignStartVariables(Object original, Map<String, Object> variables) {
        throw new OperationNotSupportedException();
    }

    @Override
    protected void dynamicAssignCompleteVariables(Object original, Map<String, Object> variables) {
        throw new OperationNotSupportedException();
    }

    @Override
    public String historyUserTaskQuery(String taskId) {
        List<Map<String, String>> executeResult = commandExecutionService.executeCommand(new QueryHistoryUserTaskCmd(taskId));
        return Result.success(executeResult);
    }
    @Override
    public String reject(String taskId) {
        return commandExecutionService.executeRejectCommand(taskId, 1, null);
    }

    @Override
    public String reject2Apply(String taskId) {
        return commandExecutionService.executeRejectCommand(taskId, 2, null);
    }

    @Override
    public String reject2Any(String body) {
        JSONObject bodyJson = JSONObject.parseObject(body);
        String taskId = bodyJson.getString("taskId");
        String targetActivityId = bodyJson.getString("targetActivityId");
        return commandExecutionService.executeRejectCommand(taskId, 3, targetActivityId);
    }

}
